package bloodfang.gui;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;

import bloodfang.Stat;
import bloodfang.StatBlock;
import au.com.bytecode.opencsv.CSVReader;

public class DBCReader {
	
	private static DBCReader instance = new DBCReader();

	private CSVReader reader = null;
	private HashMap<Integer,String[]> item_data = read("data/WoD_item_data.csv",0);
	private HashMap<Integer,String[]> item_damage_one_hand = read("data/WoD_ItemDamageOneHand.dbc.csv",0);
	private HashMap<Integer,String[]> random_prop_points = read("data/WoD_RandPropPoints.dbc.csv",0);
	private HashMap<Integer,String[]> random_suffix_data = read("data/ItemRandomSuffix.dbc.csv",0);
	private HashMap<Integer,String[]> item_enchants = read("data/WoD_SpellItemEnchantments.csv",0);
	
	double ITEM_SOCKET_COST = 8.0; // for lvl 90, lvl100 = 30
	double ENCHANT_SCALING = 8; // for lvl 90 // lvl100 = 80
	
	private DBCReader() {}
	
	private String format(String input){
		return input.replace("\"", "").replace("{", "").replace("}", "").trim();
	}
	
	private HashMap<Integer,String[]> read(String file,int field){
		HashMap<Integer,String[]> data = new HashMap<Integer,String[]>();
		try {
			reader = new CSVReader(new FileReader(file));
			String[] nextLine = null;
			while ((nextLine = reader.readNext()) != null) {
				if(nextLine.length == 1) continue;
				nextLine[field] = format(nextLine[field]);
				try{
					data.put(Integer.parseInt(nextLine[field]),nextLine);
				}catch(NumberFormatException nfe) {}
		    }
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return data;
	}
	
	// working
	private void populate_item_upgrade_level(Item item){ 
	    String[] row = item_data.get(item.getId());
	    if(row == null){
	      //System.out.println("no item data found");
	      return;
	    }
	    String[] base = random_prop_points.get(item.getItemLevel());
	    
//	    for(int i = 0;i< row.length;i++){
//	    	row[i] = format(row[i]);
//	    	System.out.println(i + " " + row[i]);
//	    }
	    
	    int offset = 2; // wod files offset
	    for(int i = 0+offset;i < 10+offset; i++){
	    	if (row[17+i].equals("-1"))
	    		break;
	      
			int enchantid = Integer.parseInt(row[17+i]);
			double multiplier = Double.parseDouble(row[37+i]);
			double socket_mult = Double.parseDouble(row[47+i]);
			double basevalue = Integer.parseInt(base[1+QualityIndex(item.getQuality()) * 5 + SlotIndex(item.getInventorySlot())]);
			if(enchantid != 0){
				int statid = enchantid;
				double value2 = (multiplier/10000.0) * basevalue - socket_mult * ITEM_SOCKET_COST;
				int value = (int) Math.round(value2);
				Stat stat = getStat(statid);
				if(stat != null)
					item.setStat(stat, value);
			}
	    }
	    // if weapon, update dps
	    if(item.getSpeed() != 0.0){
	    	String[] row2 = item_damage_one_hand.get(item.getItemLevel());
	    	item.setDps(Double.parseDouble(row2[1+item.getQuality()]));
	    }
	}
	
	private void populate_item_upgrade_level_with_random_suffix(Item item, int random_suffix) {
		String[] row = random_suffix_data.get(random_suffix);
	    if(row == null)
	        return;
	    String[] base = random_prop_points.get(item.getItemLevel());
	    for(int i = 0;i < 5; i++){
	        int enchantid = Integer.parseInt(row[3+i]);
	        double multiplier = Integer.parseInt(row[8+i]);
	        double basevalue = Integer.parseInt(base[1+QualityIndex(item.getQuality()) * 5 + SlotIndex(item.getInventorySlot())]);
	        if(enchantid != 0){
	        	int statid = Integer.parseInt(item_enchants.get(enchantid)[14]);
	        	Stat stat = getStat(statid);
	        	int value = (int) (multiplier/10000.0 * basevalue);
	        	if(stat != null)
	        		item.setStat(stat, value);
	        }
	    }		
	}
	
//	public StatBlock getSocketBonus(int id){
//        String[] enchant_row = item_enchants.get(id);
//        
//        int statid = Integer.parseInt(enchant_row[14]);
//        Stat stat = getStat(statid);
//        int statvalue = Integer.parseInt(enchant_row[11]);
//        System.out.println(id + " " + enchant_row[14] + " " + enchant_row[11]);
//        System.out.println(statid + " " + statvalue);
//        StatBlock sb = new StatBlock(stat, statvalue);
//        System.out.println(sb);
//        return sb;
//	}
	
	private static Stat getStat(int id)
    {
		switch (id)
        {
            case 3:
                return Stat.agi;
            case 4:
                return Stat.str;
            case 32:
                return Stat.cri;
            case 36:
                return Stat.hst;
//            case 31:
//                return Stat.hit;
//            case 37:
//                return Stat.exp;
            case 49:
                return Stat.mst;
//            case 35:
//            	return Stat.res;
//            case 45:
//            	return Stat.sp;
//            case 6:
//                return Stat.spi;
//            case 13:
//            	return Stat.dodge;
//            case 7:
//                return Stat.sta;
//            case 5:
//                return Stat.intt;
//            case 57:
//            	return Stat.pvppower;
            case 59:
            	return Stat.mul;
        }
        new Exception("Statid not found: " + id);
        return null;
    }
	
//	public boolean isUpgradable(Item item){
//	    String[] row = ruleset_item_upgrade.get(item.getId());
//	    if(row == null)
//	      return false;
//	    return true;
//	}
	
	private int QualityIndex(int quality){
        switch (quality)
        { 
            case 4:
            default:
                return 0;
            case 3:
                return 1;
            case 2:
                return 2;
        }
    }
	
	private int SlotIndex(int slot) {
		switch (slot) {
			case 1:
			case 5:
			case 7:
		    //case ItemSlot.TwoHand:
				return 0;
			case 3:
			case 10:
			case 6:
			case 8:
			case 12:
				return 1;
			case 9:
			case 2:
			case 16:
			case 11:
			//case ItemSlot.OffHand:
			default:
				return 2;
			//case ItemSlot.MainHand:
			case 13: // ItemSlot.OneHand:
				return 3;
			case 15: // ItemSlot.Ranged:
				return 4;
		 }
     }
	 
	 private Stat StatFromEnchantmentId(int id) {
         switch (id) {
             case 2802:
                 return Stat.agi;
//             case 2803:
//                 return Stat.sta;
//             case 2804:
//                 return Stat.intt;
             case 2805:
                 return Stat.str;
//             case 2806:
//                 return Stat.spi;
             case 2813:
//             case 2815:
//                 return Stat.dodge;
             //case 2816:
             //    return "Mp5";
             case 2822:
             case 2823:
                 return Stat.cri;
//             case 2824:
//                 return Stat.sp;
             case 2825:
                 return Stat.ap;
             //case 2826:
             //    return "Block Rating";
             case 3726:
                 return Stat.hst;
//             case 3727:
//                 return Stat.hit;
//             case 4058:
//                 return Stat.exp;
             case 4059:
                 return Stat.mst;
//             case 4060:
//                 return Stat.parry;
         }
         return null;
	 }

	 public StatBlock getItemStats(EquippedItem ei) {
		 Item item = ItemDB.get(ei.item_id, ei.getUpgradeLevel(), ei.getRandomSuffix());
		 this.populate_item_upgrade_level(item);
		 if(ei.getRandomSuffix() != 0)
			 this.populate_item_upgrade_level_with_random_suffix(item, ei.getRandomSuffix());

		 return item;
	 }
	
	public String getSuffixName(int id){
		String[] row = random_suffix_data.get(id);
		if(row != null){
			return row[1];
		}
		return Integer.toString(id);
	}
	
	public int getEnchantValue(int enchant, int offset) {
		String[] row = item_enchants.get(enchant);
		if(row != null){
			double value = Double.parseDouble(row[17+offset]);
			return (int) Math.round(value * ENCHANT_SCALING);
		}
		return 0;
	}
	
	public String getEnchantName(int enchant) {
		String[] row = item_enchants.get(enchant);
		if(row != null){
			String ret = row[row.length-2];
			for(int i = 0; i < 2; i++){
				int val = getEnchantValue(enchant,i);
				if(val != 0){
					ret = ret.replace("$k"+(i+1), Integer.toString(val));
				}
			}
			return ret;
		}
		return Integer.toString(enchant);
	}
	
    public static DBCReader getInstance() {
        return instance;
    }

	public StatBlock getEnchantStats(EquippedItem ei) {
		StatBlock enchantStats = new StatBlock();
		String[] row = item_enchants.get(ei.getEnchant());
		System.out.println(Arrays.toString(row));
		if(row != null){
			for(int i = 0; i < 2; i++) {
				int statid = Integer.parseInt(row[14+i]);
				Stat stat = getStat(statid);
				if(stat != null) {
					double scale_factor = Double.parseDouble(row[17+i]);
					int value = (int) Math.round(scale_factor * ENCHANT_SCALING);
					enchantStats.addStat(stat, value);
				}
			}
		}
		return enchantStats;	
	}
}